#include "sceneNode.h"

using namespace sde;
    
SceneNode::SceneNode(std::string _type, std::string _name, Object* _object) :
    Action("SceneNode",_type,_name,_object),
    sceneNode(0),
    parentSceneNode(0),
    sceneManager(0),
    gfxServer(0) {
    initDepend = "gfx/GfxServer";
}
    
void SceneNode::run() {
    gfxServer = (GfxServer*)Action::getFirstActionOfArchetype("gfx/GfxServer");
    
    if (gfxServer) {
        sceneManager = gfxServer->getSceneManager();
        if (sceneManager) {
        
            sceneNode = sceneManager->getRootSceneNode()->createChildSceneNode(object->name);
            parentSceneNode = sceneManager->getRootSceneNode();
        
            updateParent(object->getVar("parent",Var(std::string(""))));
            object->subscribeSetVar("parent",boost::bind(&SceneNode::updateParent,this,_1));
            
            updatePosition(object->getVar("position",Var(Vector3(0,0,0))));
            object->subscribeSetVar("position",boost::bind(&SceneNode::updatePosition,this,_1));
            
            updateRotation(object->getVar("rotation",Var(Quaternion::IDENTITY)));
            object->subscribeSetVar("rotation",boost::bind(&SceneNode::updateRotation,this,_1));
            
            updateScale(object->getVar("scale",Var(Vector3(1,1,1))));
            object->subscribeSetVar("scale",boost::bind(&SceneNode::updateScale,this,_1));
            
            updateShown(object->getVar("shown",Var(true)));
            object->subscribeSetVar("shown",boost::bind(&SceneNode::updateShown,this,_1));
            
            updateShowBoundingBox(object->getVar("showBoundingBox",Var(false)));
            object->subscribeSetVar("showBoundingBox",boost::bind(&SceneNode::updateShowBoundingBox,this,_1));
        }
    } else
        log("ERROR: couldn't find gfxServer");
}

void SceneNode::updateParent(Var val) {
    if (parentSceneNode)
        parentSceneNode->removeChild(sceneNode);
        
    parentSceneNode = 0;
    
    Object* parentObject = object->getObject(boost::any_cast<std::string>(val));
    if (parentObject) {
        SceneNode* parentSceneNodeAction = (SceneNode*)parentObject->getFirstActionOfArchetype("SceneNode");
        if (parentSceneNodeAction)
            parentSceneNode = parentSceneNodeAction->sceneNode;
    }
    
    if (!parentSceneNode && gfxServer)
        parentSceneNode = gfxServer->getSceneManager()->getRootSceneNode();
        
    if (parentSceneNode)
        parentSceneNode->addChild(sceneNode);
}

void SceneNode::updatePosition(Var val) {
    if (boost::any_cast<Vector3>(&val) && sceneNode) {
        Vector3 v = boost::any_cast<Vector3>(val);
//         log("set position %s",v.toString().c_str());
        sceneNode->setPosition(GfxServer::VectorToOgreVector(v));
    }
}

void SceneNode::updateRotation(Var val) {
    if (boost::any_cast<Quaternion>(&val) && sceneNode) {
        Quaternion q = boost::any_cast<Quaternion>(val);
        sceneNode->setOrientation(GfxServer::QuaternionToOgreQuaternion(q));
    }
}

void SceneNode::updateScale(Var val) {
    if (boost::any_cast<Vector3>(&val) && sceneNode) {
        Vector3 v = boost::any_cast<Vector3>(val);
        sceneNode->setScale(GfxServer::VectorToOgreVector(v));
    }
}

void SceneNode::updateShown(Var val) {
    if (boost::any_cast<bool>(&val) && sceneNode) {
        bool b = boost::any_cast<bool>(val);
        sceneNode->setVisible(b);
    }
}

void SceneNode::updateShowBoundingBox(Var val) {
    if (boost::any_cast<bool>(&val) && sceneNode) {
        bool b = boost::any_cast<bool>(val);
        sceneNode->showBoundingBox(b);
    }
}

void SceneNode::stop() {
    if (parentSceneNode)
        parentSceneNode->removeAndDestroyChild(sceneNode->getName());
}
